package com.fqgj.sentry.policy.engine.resolver;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fqgj.sentry.policy.engine.domain.Condition;
import com.fqgj.sentry.policy.engine.domain.ConditionGroup;
import com.fqgj.sentry.policy.engine.domain.Decision;
import com.fqgj.sentry.policy.engine.domain.enums.ConditionComposeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.ConditionGroupComposeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.ConditionGroupTypeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.PolicyTypeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.RuleComposeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.RuleTypeEnum;
import com.fqgj.sentry.policy.engine.domain.enums.VariableTypeEnum;
import com.fqgj.sentry.policy.engine.domain.Policy;
import com.fqgj.sentry.policy.engine.domain.PolicySet;
import com.fqgj.sentry.policy.engine.domain.Rule;
import com.fqgj.sentry.policy.engine.domain.ScoreCalculator;
import com.fqgj.sentry.policy.engine.domain.Variable;
import com.fqgj.sentry.policy.engine.domain.VariableMap;
import com.fqgj.sentry.policy.engine.domain.VariableOrConstant;
import com.fqgj.sentry.policy.engine.domain.Weight;
import com.fqgj.sentry.policy.engine.domain.WeightRange;
import com.fqgj.sentry.policy.engine.utils.Utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

public class GenPolicySet {
    public static void main(String[] args) {
        ObjectMapper mapper = new ObjectMapper();

        ObjectMapper configure = mapper.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);

        String json = null;
        PolicySet p = buildPolicySet();
        try {
            json = mapper.writeValueAsString(p);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        System.out.println(json);
        String path = Utils.getPath() + "policies/policySetGenForParse.json";
        System.out.println(path);
        Utils.writeToFile(path, json);
        try {
            PolicySet p1 = mapper.readValue(json, PolicySet.class);
            System.out.println(p1);
            Parser par = new Parser();
            //处理
            PolicySet p2 = par.processPolicySet(p1);
            String json1 = mapper.writeValueAsString(p2);
            System.out.println(json1);
            String path1 = Utils.getPath() + "policies/policySetParsedResult.json";
            Utils.writeToFile(path1, json1);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static PolicySet buildPolicySet() {
        PolicySet ps = new PolicySet();
        ps.setEventId(1L);
        ps.setInputVarMap(genVarMap());
        ps.setPolicySetId(UUID.randomUUID().getLeastSignificantBits());
        ps.setInputVarMap(genVarMap());
        List<Policy> psl = new ArrayList();
        psl.add(buildPolicy());
        ps.setPolicySet(psl);
        return ps;
    }

    public static Policy buildPolicy() {
        Policy policy = new Policy();
        policy.setPolicyId(UUID.randomUUID().getLeastSignificantBits());
//        policy.setPolicyType(PolicyTypeEnum.DECIDE);
        policy.setPolicyType(PolicyTypeEnum.SCORE);
        policy.setRuleCompose(RuleComposeEnum.WEIGHT);
        policy.setRuleList(buildRuleList());
        policy.setPolicyResult(null);
        policy.setInitalScoreVariable(null);
        try {
            policy.setWeightRange(genWeightRange());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return policy;
    }


    public static Rule buildRule() {
        Rule r = new Rule();
        r.setConditionGroupCompose(ConditionGroupComposeEnum.ALL);
        r.setHitDecisionOption(genDecision("REJECT"));
        r.setRuleType(RuleTypeEnum.CUSTOM);
        r.setWeight(buildWeight());
        r.setRuleResult(null);

        List<ConditionGroup> cgl = new ArrayList<>();
        {
            ConditionGroup cg = buildConditionGroup();
            cgl.add(cg);
        }
        r.setConditionGroups(cgl);
        r.setRuleId(UUID.randomUUID().getLeastSignificantBits());
        r.setRuleName("user_profile公司名称异常");
        return r;
    }

    public static List<Rule> buildRuleList() {
        List l = new ArrayList();

        Rule r = buildRule();
        l.add(r);

        return l;
    }

    public static ConditionGroup buildConditionGroup() {
        ConditionGroup cg = new ConditionGroup();
        cg.setConditionGroupType(ConditionGroupTypeEnum.GROUP);
        cg.setConditionCompose(ConditionComposeEnum.OR);
        cg.setScoreCalculator(buildScoreCalculator());
        List<Condition> cl = new ArrayList();
        {

            Condition c = buildCondition("contains", genVar(), "派出所");
            cl.add(c);
        }
        {
            Condition c = buildCondition("contains", genVar(), "资产管理");
            cl.add(c);
        }
        {
            Condition c = buildCondition("contains", genVar(), "投资管理");
            cl.add(c);
        }
        {
            Condition c = buildCondition("contains", genVar(), "执法大队");
            cl.add(c);
        }
        {
            Condition c = buildCondition("contains", genVar(), "法院");
            cl.add(c);
        }
        {
            Condition c = buildCondition("contains", genVar(), "公安局");
            cl.add(c);
        }
        {
            Condition c = buildCondition("contains", genVar(), "特警支队");
            cl.add(c);
        }
        {
            Condition c = buildCondition("contains", genVar(), "互联网金融");
            cl.add(c);
        }

        cg.setConditions(cl);
        cg.setConditionGroupResult(null);
        cg.setScoreCalculator(buildScoreCalculator());
        return cg;
    }


    public static Condition buildCondition(String op, Variable v, Object para) {
        Condition c = new Condition();
        c.setOperation(op);
        c.setHit(false);
        c.setFirstVariable(v);
        VariableOrConstant voc = new VariableOrConstant();
        voc.setIsVar(false);
        voc.setConstant(para);
        c.setSecondVariable(voc);
        return c;
    }

    public static Weight buildWeight() {
        Weight w = new Weight();
        Double[] para = new Double[]{10d, 0d};
        List<Object> params = Arrays.asList(para);
        w.setParams(params);
        w.setVariable(genVar("company_name", VariableTypeEnum.DOUBLE, 0d));
        w.setWeightExpression("weightScore");

        return w;
    }

    public static ScoreCalculator buildScoreCalculator() {
        ScoreCalculator sc = new ScoreCalculator();
        Double[] para = new Double[]{10d, 0d};
        List<Object> params = Arrays.asList(para);
        sc.setParams(params);
        VariableOrConstant voc = new VariableOrConstant();
        voc.setIsVar(true);
        voc.setVariable(genVar("score", VariableTypeEnum.DOUBLE, 1));
        sc.setVariable(voc);
        sc.setExpression("calculateScore");
        return sc;
    }

    public static Variable genVar() {
        return genVar("company_name", VariableTypeEnum.STRING, "派出所有限公司");
    }

    public static Variable genVar(String key, VariableTypeEnum vt, Object value) {
        Variable var = new Variable();
        var.setId(UUID.randomUUID().getLeastSignificantBits());
        var.setName(key);
        var.setValue(value);
        var.setVarType(vt);
        return var;
    }

    public static VariableMap genVarMap() {
        VariableMap varMap = new VariableMap();
        {
            String key = "company_name";
            Variable var = genVar();
            var.setName(key);
            varMap.setVariable(key, var);
        }

        return varMap;
    }

    public static Decision genDecision(String decision) {
        Decision d = new Decision();
        d.setDecisionId(UUID.randomUUID().variant());
        d.setDecisionName(decision);
        d.setPriority(0);
        return d;
    }

    public static List<WeightRange> genWeightRange() {
        List<WeightRange> ranges = new ArrayList<>();
        {
            WeightRange wr = new WeightRange();
            wr.setStart(0d);
            wr.setEnd(0d);
            wr.setDecision(genDecision("REJECT"));
            ranges.add(wr);
        }
        {
            WeightRange wr = new WeightRange();
            wr.setStart(0d);
            wr.setEnd(20d);
            wr.setDecision(genDecision("REVIEW"));
            ranges.add(wr);
        }
        {
            WeightRange wr = new WeightRange();
            wr.setStart(20d);
            wr.setEnd(100d);
            wr.setDecision(genDecision("ACCEPT"));
            ranges.add(wr);
        }
        return ranges;
    }
}
